/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.variableengine.core.dtm;

import com.inspur.edp.bef.component.detailcmpentity.udtdetermination.UDTDtmComponent;
import com.inspur.edp.bef.component.detailcmpentity.udtdetermination.UDTDtmMethod;
import com.inspur.edp.cdf.component.api.service.ComponentInvokeService;
import com.inspur.edp.cef.api.determination.ICefDeterminationContext;
import com.inspur.edp.cef.designtime.api.operation.CommonDetermination;
import com.inspur.edp.cef.designtime.api.variable.CommonVariableEntity;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.changeset.Util;
import com.inspur.edp.cef.spi.determination.IDetermination;
import com.inspur.edp.cef.variable.spi.determination.AbstractVariableDetermination;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataCustomizationFilter;
import com.inspur.edp.lcm.metadata.api.service.MetadataRTService;
import com.inspur.edp.metadata.rtcustomization.api.CustomizationRtService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;

public class VariableEngineDtmAdaptor implements IDetermination {

  private CommonDetermination dtm;
  private CommonVariableEntity varEntity;

  public VariableEngineDtmAdaptor(CommonVariableEntity varEntity, CommonDetermination dtm) {
    this.dtm = dtm;
    this.varEntity = varEntity;
  }

  @Override
  public String getName() {
    return dtm.getName();
  }

  @Override
  public boolean canExecute(IChangeDetail change) {
    if (getElements().length == 0) {
      return true;
    }
    if (change != null && Util.containsAny(change, getElements())) {
      return true;
    }
    return false;
  }

  private String[] elements;

  private String[] getElements() {
    if (elements == null) {
      if (dtm.getRequestElements() == null || dtm.getRequestElements().isEmpty()) {
        elements = new String[0];
      } else {
        elements = dtm.getRequestElements().stream()
            .map(item -> varEntity.findElement(item).getLabelID()).toArray(String[]::new);
      }
    }
    return elements;
  }

  private Class componentClass;

  private Class getMethod() {
    if (componentClass == null) {
      MetadataCustomizationFilter filter = new MetadataCustomizationFilter();
      filter.setMetadataId(dtm.getComponentId());
      filter.setIsI18n(false);
      GspMetadata metadata = SpringBeanUtils.getBean(MetadataRTService.class).getMetadata(filter);

      UDTDtmComponent component = (UDTDtmComponent) metadata.getContent();
      UDTDtmMethod method = component.getUdtDtmMethod();
      try {
        componentClass = Class.forName(method.getClassName());
      } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
      }
    }
    return componentClass;
  }

  @Override
  public void execute(ICefDeterminationContext context, IChangeDetail change) {
    Constructor constructor = null;
    ComponentInvokeService componentInvokeService = SpringBeanUtils.getBean(ComponentInvokeService.class);
    try {
      //constructor = getMethod().getConstructors()[0];
      String componentId = dtm.getComponentId();
      List<Object> params = Arrays.asList(context, change);
      AbstractVariableDetermination determinationAction = (AbstractVariableDetermination) componentInvokeService.getInstance(componentId, params);

//      AbstractVariableDetermination determinationAction = (AbstractVariableDetermination) constructor
//          .newInstance(context, change);
      determinationAction.Do();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}
